<?php
/*
 * @Author: 代勇 1031850847@qq.com
 * @Date: 2023-01-30 17:24:29
 * @LastEditors: 代勇 1031850847@qq.com
 * @LastEditTime: 2024-03-27 09:27:40
 * @Description: 文件操作
 */

namespace Daiyong;

class File {
    public static $path =  '../../../../'; //当前项目路径

    /**
     * @description: 获取当前项目的绝对地址,没有文件夹则创建
     * @param {*} $file 文件相对项目地址或者绝对地址
     * @param {*} $createDir 如果没有文件夹是否创建
     * @return {*}
     */
    public static function path($file = '', $createDir = false) {
        $root = __DIR__ . '/' . self::$path;
        if (!$file) {
            return $root;
        } else {
            if (!(strpos($file, '/') === 0 || preg_match('/^[A-Z]:/', $file))) {
                $path = $root . $file;
            } else {
                $path = $file;
            }
            if ($createDir) {
                if (!is_dir(dirname($path))) {
                    mkdir(dirname($path), 0777, true);
                }
            }
            return $path;
        }
    }

    /**
     * @description: 写入文件
     * @param {string} $file 文件路径
     * @param {string} $content 文件内容
     * @param {*} $append 是否追加
     * @return {boolean}
     */
    public static function put($file = '', $content = '', $append = '') {
        $file = self::path($file, true);
        if (!is_file($file)) {
            touch($file);
            chmod($file, 0777);
        }
        if ($append) {
            $return = file_put_contents($file, $content . PHP_EOL, FILE_APPEND);
        } else {
            $return = file_put_contents($file, $content);
        }
        if (!$return && $return !== 0) {
            return false;
        }
        return true;
    }

    /**
     * @description: 获取文件信息
     * @param {string} $file 文件路径,可以为相对路径
     * @return {string}
     */
    public static function get($file) {
        return @file_get_contents(self::path($file));
    }

    /**
     * @description: 删除文件
     * @param {string} $file 文件路径,可以为相对路径
     * @return {boolean}
     */
    public static function delete($file) {
        return unlink(self::path($file));
    }

    /**
     * @description: 获取文件夹目录
     * @param {string} $dir 路径位置
     * @param {array} $filter1 需要过滤掉的文件夹
     * @param {array} $filter2 需要过滤掉的文件夹
     * @return {array} 目录列表
     */
    public static function lists($dir, $filter1 = array(), $filter2 = array('.git/', '.svn/', 'node_modules/', 'vendor/')) {
        $filter = array_merge($filter1, $filter2);
        $dir = self::path($dir);
        $fileList = array();
        $dirList = array();
        $list = scandir($dir);
        foreach ($list as $v) {
            if ($v == "." || $v == "..") continue;
            $fileOrDirPath = $dir . '/' . $v;
            if (is_file($fileOrDirPath)) {
                if (self::filter($v, $filter)) continue;
                $size = filesize($fileOrDirPath);
                $fileList[] = array(
                    'name' => $v,
                    'type' => 'file',
                    'size' => $size
                );
            } else {
                if (self::filter($v . '/', $filter)) continue;
                $childInfo = scandir($fileOrDirPath);
                $childCount = 0;
                foreach ($childInfo as $v2) {
                    if ($v2 == "." || $v2 == "..") continue;
                    if (!is_file($fileOrDirPath . '/' . $v2)) {
                        if (in_array($v2, $filter)) continue;
                    }
                    $childCount++;
                }
                $dirList[] = array(
                    'name' => $v,
                    'type' => 'dir',
                    'childCount' => $childCount
                );
            }
        }
        return array_merge($dirList, $fileList);
    }

    /**
     * @description: 获取文件夹数形目录
     * @param {string} $dir 文件夹目录
     * @param {array} $filter1 需要过滤掉的文件夹
     * @param {array} $filter2 需要过滤掉的文件夹
     * @return {array} 树形结构
     */
    public static function tree($dir,  $filter1 = array(), $filter2 = array('.git/', '.svn/', 'node_modules/', 'vendor/')) {
        $list = self::lists($dir, $filter1, $filter2);
        foreach ($list as $k => $v) {
            if ($v['type'] == 'dir') {
                $list[$k]['child'] = self::tree($dir . '/' . $v['name'],  $filter1, $filter2);
            }
        }
        return $list;
    }

    /**
     * @description: 将树形目录结构转换成文件列表
     * @param {array} $tree 树形结构数据
     * @return {array} 文件列表
     */
    public static function treeToList($tree, $fileSize = false) {
        $list = array();
        foreach ($tree as $v) {
            if ($v['type'] == 'dir') {
                if (isset($v['child']) && $v['child']) {
                    $childList = self::treeToList($v['child'], $fileSize);
                    foreach ($childList as $k2 => $v2) {
                        $childList[$k2] = $v['name'] . '/' . $v2;
                    }
                    $list = array_merge($list, $childList);
                }
            } else {
                $list[] = $v['name'] . ($fileSize ? ' ' . $v['size'] : '');
            }
        }
        return $list;
    }

    /**
     * @description: 字符串是否在数组里面可为正则
     * @param {string} $str 字符串
     * @param {string} $filter 过滤规则,可为正则
     * @return {boolean}
     */
    private static function filter($str, $filter) {
        if (in_array($str, $filter)) return true;
        $continue = false;
        foreach ($filter as $v) {
            if (preg_match('/^\/.*?\/$/', $v)) {
                if (preg_match($v, $str)) $continue = true;
            }
        }
        return $continue;
    }
}
